package jmine.tec.utils.cripto;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import jmine.tec.utils.cripto.exception.CriptoException;
import jmine.tec.utils.cripto.key.impl.DefaultPasswordManager;
import jmine.tec.utils.io.EncodingUtils;
import bancosys.tec.utils.md5sum.MD5SumTool;

public class PasswordFileGenerator {

    private static final int SEED_LENGTH = 8;

    public static void main(String[] args) throws Exception {
        String fileName = args[0];
        String password = args[1];
        Cipher cipher = getCipher();
        cipher.init(Cipher.ENCRYPT_MODE, getKey());
        byte[] data = cipher.doFinal(password.getBytes("UTF-8"));
        FileOutputStream fout = new FileOutputStream(fileName);
        try {
            fout.write(data);
        } finally {
            fout.close();
        }
    }

    /**
     * devolve um array que deve ser usado para
     * 
     * @return byte[]
     */
    private static byte[] getSeed() {
        InputStream stream =
                DefaultPasswordManager.class.getClassLoader().getResourceAsStream(
                        "jmine/tec/utils/cripto/key/impl/DefaultPasswordManager.class");
        final int iterSize = 4;
        try {
            byte[] md5 = EncodingUtils.toASCII(MD5SumTool.md5Sum(stream));
            byte[] result = new byte[SEED_LENGTH];
            for (int i = 0; i < SEED_LENGTH; i++) {
                result[i] = md5[i];
                for (int j = 1; j < iterSize; j++) {
                    result[i] ^= md5[i + SEED_LENGTH * j];
                }
            }
            return result;
        } catch (IOException e) {
            throw new IllegalStateException("Cannot find own class file");
        }
    }

    protected static Cipher getCipher() {
        try {
            return Cipher.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException();
        } catch (NoSuchPaddingException e) {
            throw new IllegalStateException();
        }
    }

    protected static Key getKey() {
        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            KeySpec spec = new DESKeySpec(getSeed());
            return factory.generateSecret(spec);
        } catch (NoSuchAlgorithmException e) {
            throw new CriptoException("DES not available", e);
        } catch (InvalidKeyException e) {
            throw new CriptoException("Cannot create a Key", e);
        } catch (InvalidKeySpecException e) {
            throw new CriptoException("Invalid KeySpec", e);
        }
    }

}
